<?php
/**
 * Created by PhpStorm.
 * User: yangjiaming
 * Date: 2018/2/5
 * Time: 15:41
 */

namespace Halo\Data;

use \PDO;
use \Exception;
class MySql
{
    public $dbh;
    protected $transLevel = 0;
    public $error;
    private static $config = [];
    public function __construct($config)
    {
        $port = isset($config['port']) ? $config['port'] : 3306;
        self::$config = $config;
        $dsn = sprintf('mysql:host=%s;dbname=%s;port=%d', $config['host'], $config['dbname'], $port);
        try{
            //Logger::debug('连接数据库');
            $this->dbh = new PDO($dsn, $config['user'], $config['pass'],
                array(
                    PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES \'utf8\'',
                    PDO::ATTR_PERSISTENT => false,
                    PDO::ATTR_EMULATE_PREPARES => true,
                    PDO::ATTR_STRINGIFY_FETCHES => false,
                    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                ));
        }catch(\PDOException $e){
            $this->error = $e->getmessage();
            //Logger::debug('连接出错：'.$e->getmessage());
            throw $e;
        }
    }

    public function insertTable($table, $data)
    {
        if (!is_array($data))
            return false;
        list($fields, $values) = $this->getConditionArray($data);
        if(count($values)) {
            $sql = sprintf('INSERT INTO %s SET %s', $table, $fields);

            $this->query($sql, $values);
            return intval($this->dbh->lastInsertId());
        }
        return false;
    }
    public function getRowByCondition($table, $condition, $fields = '')
    {
        list($condition, $values) = $this->getConditionPair($condition);
        if (empty($fields))
            $sql = sprintf('SELECT * FROM %s WHERE %s LIMIT 1', $table, $condition);
        else
            $sql = sprintf('SELECT %s FROM %s WHERE %s LIMIT 1', $fields, $table, $condition);

        return $this->get_row($sql, $values);
    }
    public function getConditionArray($data)
    {
        if (count($data) == 0)
            return array(null, null);

        $fields = array();
        $values = array();
        foreach ($data as $k => $v) {
            $fields[] = sprintf('%s=?', $k);
            $values[] = $v;
        }

        return array(implode(',', $fields), $values);
    }
    public function query($sql, $values = null,$ignore_error=false)
    {
        try {
            $stmt = $this->dbh->prepare($sql);
            $stmt->execute($values);
            return $stmt;
        } catch (Exception $e) {
            /*Logger::info('SQL_QUERY_ERROR', array('error'=>$e->getMessage(),'sql'=>$sql, 'values'=>$values));*/
            self::resetConnect($e->getMessage()); // 出错时调用重置连接
            if(!$ignore_error) {
                throw $e;
            }
        }
    }
    public function resetConnect($err_msg)
    {
        if(strpos($err_msg, 'server has gone away') !== false || strpos($err_msg, '[2002]') !== false || strpos($err_msg, 'General error') !== false){
            Remote::close('db', []);
            sleep(1);
        }
    }
    public function getConditionPair($condition)
    {
        if (is_array($condition)) {
            return $condition;
        }

        if (empty($condition) || is_string($condition))
        {
            return array($condition, null);
        }
    }
    public function get_var($sql, $values = null)
    {
        return $this->query($sql, $values)->fetchColumn(0);
    }

//
    public function get_row($sql, $values = null)
    {
        return $this->query($sql, $values)->fetch(PDO::FETCH_ASSOC);
    }

    public function get_col($sql, $values = null, $offset = 0)
    {
        return $this->query($sql, $values)->fetchAll(PDO::FETCH_COLUMN, $offset);
    }

    public function get_results($sql, $values = null)
    {
        return $this->query($sql, $values)->fetchAll(PDO::FETCH_ASSOC);
    }

    function escape($str) {
        return $this->dbh->quote($str);
    }
}